local CalcCoords = require 'util/tools'
local Quick = require 'util/quick_wp_laser_beam'

local function MoveLaser(doer, invobj, act_pos_x, act_pos_z)
    if invobj.movelaser == nil then
        invobj.movelaser = SpawnPrefab('fx_laserbeem_blue_particle')
        local doer_x, doer_y, doer_z = doer.Transform:GetWorldPosition()                       -- 人物坐标
        local act_angle = CalcCoords:angleBetweenVectors(doer_x, doer_z, act_pos_x, act_pos_z) -- 人物到施法点的方向与默认方向的转角
        local doer_radian_angle = (act_angle - 90) * math.pi / 180                             -- 转成弧度
        local fx_len = 28                                                                      -- 特效实际长度(自行测试)
        local iter_range = 2                                                                   -- 扫描半径

        invobj.movelaser.Transform:SetPosition(doer_x, doer_y + 1.5, doer_z)
        invobj.movelaser.Transform:SetRotation(act_angle)
        invobj.movelaser.Transform:SetScale(2, 2, 2)

        invobj.movelaser.task_period_update_recoil = invobj.movelaser:DoPeriodicTask(0.02, function(inst)
            local doer_x, doer_y, doer_z = doer.Transform:GetWorldPosition()
            invobj.movelaser.Transform:SetPosition(doer_x, doer_y + 1.5, doer_z)

            local mouse_x, _, mouse_z = ConsoleWorldPosition():Get()                                    -- 鼠标坐标
            local mouse_angle = CalcCoords:angleBetweenVectors(doer_x, doer_z, mouse_x, mouse_z)        -- 人物到鼠标的方向与默认方向的转角
            invobj.movelaser.Transform:SetRotation(mouse_angle)                                         -- 根据鼠标位置更新旋转角度
            local dist_btw_doer_and_mouse = CalcCoords:calcDist(doer_x, doer_z, mouse_x, mouse_z, true) -- 人物到鼠标的距离
            for dist = iter_range, fx_len, iter_range * 2 do                                            -- 找到线上的实体
                local iter_x, iter_z = CalcCoords:findPointOnLine(mouse_x, mouse_z, doer_x, doer_z,
                    dist_btw_doer_and_mouse, dist)                                                      -- 根据距离找到线上的点
                local ents = TheSim:FindEntities(iter_x, 1, iter_z, iter_range, { 'locomotor' },
                    { 'INLIMBO', 'player', 'companion', 'wall' })
                for _, v in pairs(ents) do
                    if v and v.components and v.components.health and not v.components.health:IsDead() and
                        v.components.combat then
                        v.components.combat:GetAttacked(doer, 20)    --没有位移组件都给我吃两倍伤害                                   -- 伤害
                        if v.components.locomotor then
                            local v_x, _, v_z = v.Transform:GetWorldPosition()                          -- 敌人坐标
                            local dist_btw_v_and_doer = CalcCoords:calcDist(doer_x, doer_z, v_x, v_z, true) -- 人物到敌人的距离
                            local des_x, des_z = CalcCoords:findPointOnLine(v_x, v_z, doer_x, doer_z, dist_btw_v_and_doer,
                                dist_btw_v_and_doer + 1)                                                -- 击退
                            v.Physics:Teleport(des_x, 0, des_z)
                        else  v.components.combat:GetAttacked(doer, 20) 
                        end
                    end
                end
            end
        end)
    else
        invobj.movelaser:Remove()
        invobj.movelaser = nil
        -- if invobj.movelaser.task_period_update_recoil then invobj.movelaser.task_period_update_recoil:Cancel()invobj.movelaser.task_period_update_recoil=nil end
    end
end

local actions = { {
    id = 'WP_LASER_BEAM',
    str = '射死你们',
    fn = function(act)
        if act.doer ~= nil then
            local act_pos = act:GetActionPoint()
            return MoveLaser(act.doer, act.invobject, act_pos.x, act_pos.z)
        end
    end,
    state = 'quickcastspell',
    actiondata = {
        -- priority = 99,
        -- mount_valid = false,
        distance = 30
    }
} -- {
    -- 	id = 'WP_LASER_BEAM_STOP',
    -- 	str = '饶你一命',
    -- 	fn = function(act)
    -- 		if act.doer ~= nil then
    --             local act_pos = act:GetActionPoint()
    -- 			return StopMoveLaser(act.invobject)
    -- 		end
    -- 	end,
    -- 	state = 'quickcastspell',
    -- 	actiondata = {
    -- 		-- priority = 98,
    -- 		-- mount_valid = false,
    --         distance = 30,
    -- 	},
    -- },
}

local component_actions = { {
    type = 'POINT',
    component = 'spellcaster',
    tests = { {
        action = 'WP_LASER_BEAM',
        testfn = function(inst, doer, actions, invobject, right)
            -- return doer and doer.components and doer.components.inventory and doer.components.inventory and doer.components.inventory:EquipHasTag('staff_spidersquad') and target.components and target.components.inventoryitem and target.equip_changeimg_task == nil
            return doer and doer.components and doer.components.inventory and
                doer.components.inventory:EquipHasTag("obrsword")        --and invobject.movelaser == nil
        end                                                              --
    }                                                                    -- {
        -- 	action = 'WP_LASER_BEAM_STOP',
        -- 	testfn = function(inst,doer,actions,invobject,right)
        --         -- return doer and doer.components and doer.components.inventory and doer.components.inventory and doer.components.inventory:EquipHasTag('staff_spidersquad') and target.components and target.components.inventoryitem and target.equip_changeimg_task == nil
        --         return doer and doer.components and doer.components.inventory and invobject.movelaser ~= nil and invobject.movelaser.prefab and invobject.movelaser.prefab == 'wp_laser_beam'
        -- 	end,
        -- },
    }
} }

for _, act in pairs(actions) do
    local addaction = AddAction(act.id, act.str, act.fn)
    if act.actiondata then
        for k, v in pairs(act.actiondata) do
            addaction[k] = v
        end
    end

    AddStategraphActionHandler('wilson', GLOBAL.ActionHandler(addaction, act.state))
    AddStategraphActionHandler('wilson_client', GLOBAL.ActionHandler(addaction, act.state))
end

for _, v in pairs(component_actions) do
    local testfn = function(...)
        local actions = GLOBAL.select(v.type == 'POINT' and -3 or -2, ...)
        for _, data in pairs(v.tests) do
            if data and data.testfn and data.testfn(...) then
                data.action = string.upper(data.action)
                table.insert(actions, GLOBAL.ACTIONS[data.action])
            end
        end
    end
    AddComponentAction(v.type, v.component, testfn)
end
